package com.tdcoding.chat.server;

import com.tdcoding.chat.action.common.ActionRunnable;
import com.tdcoding.chat.constants.ChatConstants;
import com.tdcoding.chat.constants.MainConstants;
import com.tdcoding.chat.entities.RequestInfo;
import com.tdcoding.chat.entities.ResponseInfo;
import com.tdcoding.chat.helper.Logger;
import com.tdcoding.chat.helper.ProtostuffHelper;
import com.tdcoding.chat.helper.StringHelper;
import com.tdcoding.chat.manager.ChatManager;

import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

public class ChatHandler extends SimpleChannelInboundHandler<byte[]>{
	private ResponseInfo responseInfo;
	public ChatHandler() {
		responseInfo=new ResponseInfo();
	}

	@Override
	public void channelRead0(ChannelHandlerContext ctx, byte[] bytes)
			throws Exception {
		RequestInfo requestInfo=(RequestInfo) ProtostuffHelper.deserialize(bytes, RequestInfo.class);
		Logger.println(this, "channelRead0",requestInfo);
		if (requestInfo==null) {
			handleRespone(ctx.channel(),"","",-1,"Not found the request parameters.");
			return;
		}
		if (ChatConstants.PONG.equals(requestInfo.getMethod())) {
			Logger.println(this, "channelRead0 pong", requestInfo);
			return;
		}
		if (requestInfo==null
				||requestInfo.getPlatform()<0
				||!StringHelper.hasValue(requestInfo.getMethod())) {
			handleRespone(ctx.channel(),requestInfo.getPacketId(),"",-1,"Not found the request parameters.");
			return;
		}
		ChatManager.getInstance().executeRunnable(new ActionRunnable(ctx.channel(), requestInfo));
	}	

	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
			throws Exception {
		/* 心跳处理 */
		if (evt instanceof IdleStateEvent) {
			IdleStateEvent stateEvent = (IdleStateEvent) evt;
//			Logger.println(this, "userEventTriggered", stateEvent.state(),ctx.channel().toString());
			if (stateEvent.state() == IdleState.READER_IDLE) {
				/* 读取心跳超时 */
				ChatManager.updateChannelInfo(ctx.channel(),
						MainConstants.USER_STATUS_OFFLINE);
				ctx.channel().disconnect();
			} else if (stateEvent.state() == IdleState.WRITER_IDLE) {
	        	/* 链路空闲时发起心跳 */
//				responseInfo.setMethod(MainConstants.HEARTBEAT_PING);
//				ctx.channel().writeAndFlush(ProtostuffHelper.serialize(responseInfo));
	        }
	        else  if (stateEvent.state() == IdleState.ALL_IDLE) {
	        	/* 所有链路空闲时发起心跳 */
	        	responseInfo.setMethod(ChatConstants.PING);
	        	byte[] bytes=ProtostuffHelper.serialize(responseInfo);
//	        	String json=JJsonHelper.toJson(responseInfo);
//    			Logger.println(this, "userEventTriggered~", bytes);
				ctx.channel().writeAndFlush(bytes);
	        }
		}
	}


	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		Logger.println(this, "exceptionCaught", cause);
//		if (StringHelper.hasValue(cause.getMessage())) {
//			handleRespone(ctx.channel(), "",ChatConstants.CONNECTION_ERR,-1,cause.getMessage());
//		}
	}
	
	/**
	 * 响应请求
	 * @param channel
	 * @param packetId
	 * @param actionName
	 * @param respCode
	 * @param respData
	 */
	private ChannelFuture handleRespone(Channel channel,String packetId,String actionName,int respCode, Object... respData) {
		Logger.println(this, "handleRespone", actionName,respCode,respData);
		ResponseInfo responseInfo=new ResponseInfo();
		responseInfo.setPacketId(packetId);
		responseInfo.setRespCode(respCode);
		responseInfo.setRespData(respData);
		responseInfo.setMethod(actionName);
		ChannelFuture future=channel.writeAndFlush(responseInfo);
		Logger.println(this, "handleRespone~", future.isSuccess(),future.isDone());
		return future;
	}
	
}
